package com.meiyuetao.myt.core.service;

import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import lab.s2jh.core.exception.ServiceException;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.ctx.DynamicConfigService;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.MoreLikeThisParams;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.google.common.collect.Sets;
import com.meiyuetao.myt.crawl.dao.ParseCommodityDao;
import com.meiyuetao.myt.crawl.entity.ParseCommodity;
import com.meiyuetao.myt.md.dao.CommodityDao;
import com.meiyuetao.myt.md.entity.Brand;
import com.meiyuetao.myt.md.entity.Category;
import com.meiyuetao.myt.md.entity.Commodity;

@Service
public class SolrService {

    private final Logger logger = LoggerFactory.getLogger(BaseService.class);

    @Autowired
    private DynamicConfigService dynamicConfigService;
    @Autowired
    private ParseCommodityDao parseCommodityDao;
    @Autowired
    private CommodityDao commodityDao;
    @Value("${apache.solr.user}")
    private String solrUser;

    @Value("${apache.solr.passwd}")
    private String solrPasswd;

    private HttpClientBuilder httpClientBuilder;

    @PostConstruct
    public void buildHttpClientBuilder() {
        logger.debug("PostConstruct HttpClientBuilder...");
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(solrUser, solrPasswd));
        // 创建HttpClientBuilder
        httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
    }

    private String getSolrUrl() {
        return dynamicConfigService.getString("cfg.apache.solr.url");
    }

    /**
     * 根据传入的地理编码（经度,维度）查找距离此点最近的代理商，返回此代理商SID
     *
     * @param geocode （经度,维度）例如： 39.896887,116.329135
     * @return 代理商SID
     */
    public String findMinimumDistancePartner(String geocode) {
        // 创建查询参数以及设定的查询参数
        SolrQuery params = new SolrQuery();

        // the common parameters for all search
        params.set("q", "*:*");
        params.set("fl", "*,score");

        params.set("sfield", "store");// 经纬度坐标对应字段名
        params.set("pt", geocode);// 经纬度
        /*
         * params.set("d", 100);// 经纬度 params.set("fq", "{!geofilt}");
         */// 必须，过滤地理位置
        params.set("sort", "geodist() asc");// 排序按距离
        // 设置起始位置与返回结果数
        params.setRows(1);

        QueryResponse rsp = null;
        try {
            rsp = buildSolrServer(getSolrUrl() + "/partner").query(params);
        } catch (SolrServerException e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        // 返回查询结果
        SolrDocumentList docs = rsp.getResults();
        if (docs != null && docs.size() > 0) {
            SolrDocument doc = docs.get(0);
            String sid = doc.getFieldValue("sid").toString();
            return sid;
        }
        return null;
    }

    private void solrHttpGet(String url) {
        try {
            // HttpClient
            CloseableHttpClient httpClient = httpClientBuilder.build();

            // 执行getMethod
            HttpGet httpGet = new HttpGet(url);
            logger.debug("Http GET: {}", url);
            HttpResponse httpResponse = httpClient.execute(httpGet);
            StatusLine statusLine = httpResponse.getStatusLine();
            logger.debug("StatusLine: {} for URL: {}", statusLine, url);
            if (statusLine.getStatusCode() != 200) {
                logger.error("Http URL response NOT OK [" + statusLine + "] for: " + url);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    private SolrServer buildSolrServer(String url) {
        HttpSolrServer solr = new HttpSolrServer(url);
        return solr;

    }

    public void calcParseCommodity(ParseCommodity parseCommodity, Map<Brand, Set<String>> brandTokensMap) {
        if (parseCommodity.getTargetBrand() != null && parseCommodity.getTargetCategory() != null) {
            return;
        }
        try {

            String title = StringUtils.isNotBlank(parseCommodity.getTargetTitle()) ? parseCommodity.getTargetTitle() : parseCommodity.getTitle();

            // 基于品牌单词切分词，找出匹配程度最大的品牌作为分组
            if (parseCommodity.getTargetBrand() == null && brandTokensMap != null) {
                int maxMatch = 0;
                for (Map.Entry<Brand, Set<String>> me : brandTokensMap.entrySet()) {
                    int rowMatch = 0;
                    Set<String> matchWords = Sets.newHashSet();
                    for (String token : me.getValue()) {
                        token = token.trim().toLowerCase();
                        if (title.toLowerCase().indexOf(token) > -1) {
                            rowMatch++;
                            matchWords.add(token);
                        }
                    }
                    if (rowMatch > maxMatch) {
                        maxMatch = rowMatch;
                        parseCommodity.setTargetBrand(me.getKey());
                        parseCommodity.setTargetBrandExplain("基于品牌同义词，匹配同义词：" + StringUtils.join(matchWords, "/"));
                    }
                }
            }

            // 创建查询参数以及设定的查询参数
            SolrQuery params = new SolrQuery();

            // the common parameters for all search
            String text = cleanSpecialChar(title);
            params.set("q", text);
            params.set("defType", "edismax");
            params.set("mm", "20%");
            params.set("qf", "title");
            params.set("fl", "*,score");
            params.set("sort", "score desc");
            params.set("fq", "brand_title:* OR category_name:*");
            // 设置起始位置与返回结果数
            params.setRows(5);

            QueryResponse rsp = buildSolrServer(getSolrUrl() + "/commodity").query(params);
            // 返回查询结果
            SolrDocumentList docs = rsp.getResults();

            logger.debug("Max score: {} for {}", docs.getMaxScore(), text);
            if (logger.isDebugEnabled()) {
                for (SolrDocument doc : docs) {
                    logger.debug(" - score: {}", doc.getFieldValue("score"));
                    logger.debug(" - sid: {}", doc.getFieldValue("sid"));
                    logger.debug(" - title: {}", doc.getFieldValue("title"));
                    logger.debug(" - brand_title: {}", doc.getFieldValue("brand_title"));
                    logger.debug(" - category_name: {}", doc.getFieldValue("category_name"));
                }
            }

            if (docs != null && docs.size() > 0) {
                parseCommodity.setMatchMaxScore(docs.getMaxScore());
                parseCommodity.setMatchDocs("");
                for (SolrDocument doc : docs) {
                    String item = docs.getMaxScore() + ":" + doc.getFieldValue("barcode") + ":" + doc.getFieldValue("title");
                    if (StringUtils.isBlank(parseCommodity.getMatchDocs())) {
                        parseCommodity.setMatchDocs(item);
                    } else {
                        parseCommodity.setMatchDocs(parseCommodity.getMatchDocs() + "," + item);
                    }

                    Float score = (Float) doc.getFieldValue("score");
                    if (score < 0.3) {
                        break;
                    }
                    Commodity commodity = commodityDao.findOne(Long.valueOf((String) doc.getFieldValue("sid")));
                    if (parseCommodity.getTargetBrand() == null && commodity.getBrand() != null) {
                        parseCommodity.setTargetBrand(commodity.getBrand());
                        parseCommodity.setTargetBrandExplain(docs.getMaxScore() + ":" + doc.getFieldValue("barcode") + ":" + doc.getFieldValue("title") + ":"
                                + doc.getFieldValue("brand_title"));
                    }
                    Category category = commodity.getCategory();
                    if (parseCommodity.getTargetCategory() == null && category != null) {
                        parseCommodity.setTargetCategory(category);
                        parseCommodity.setTargetCategoryExplain(docs.getMaxScore() + ":" + doc.getFieldValue("barcode") + ":" + doc.getFieldValue("title") + ":"
                                + doc.getFieldValue("category_code") + "/" + doc.getFieldValue("category_name"));
                    }

                    if (parseCommodity.getTargetBrand() != null && parseCommodity.getTargetCategory() != null) {
                        break;
                    }
                }
                parseCommodityDao.save(parseCommodity);
            }
        } catch (SolrServerException e) {
            logger.error(e.getMessage(), e);
        }
    }

    private String cleanSpecialChar(String txt) {
        txt = StringUtils.remove(txt, "[");
        txt = StringUtils.remove(txt, "]");
        txt = StringUtils.remove(txt, "(");
        txt = StringUtils.remove(txt, ")");
        txt = StringUtils.remove(txt, "*");
        return txt;
    }

    // 优享100新增商品异步更新solr
    @Async
    public void yoxIndexAsync() {
        solrHttpGet(getSolrUrl() + "/yox/dih?command=delta-import");
    }

    @Async
    public void commodityIndexAsync() {
        solrHttpGet(getSolrUrl() + "/commodity/dih?command=delta-import");
        solrHttpGet(getSolrUrl() + "/mlt-view-commodity/dih?command=delta-import");
        solrHttpGet(getSolrUrl() + "/mlt-comb-commodity/dih?command=delta-import");
    }

    @Async
    public void themeIndexAsync() {
        solrHttpGet(getSolrUrl() + "/theme/dih?command=delta-import");
    }

    @Async
    public void partnerIndexAsync() {
        solrHttpGet(getSolrUrl() + "/partner/dih?command=delta-import");
    }

    @Async
    public void yrydStoreAsync() {
        solrHttpGet(getSolrUrl() + "/store/dih?command=delta-import");
        solrHttpGet(getSolrUrl() + "/store-commodity/dih?command=delta-import");
    }

    @Async
    public void mltViewCommodityIndexAsync() {
        solrHttpGet(getSolrUrl() + "/mlt-view-commodity/dih?command=delta-import");
    }

    public void setSolrUser(String solrUser) {
        this.solrUser = solrUser;
    }

    public void setSolrPasswd(String solrPasswd) {
        this.solrPasswd = solrPasswd;
    }

    @SuppressWarnings("unchecked")
    public SimpleOrderedMap<SolrDocumentList> searchCommodities(String keyword, int start, int rows, boolean mlt) {
        // 创建查询参数以及设定的查询参数
        SolrQuery params = new SolrQuery();
        // the common parameters for all search
        String text = cleanSpecialChar(keyword);
        params.set("q", text);
        if (mlt) {
            // params.setQueryType("/" + MoreLikeThisParams.MLT);
            params.set(MoreLikeThisParams.MLT, true);
        }

        // 设置起始位置与返回结果数
        params.setRows(rows);
        params.setStart(start);

        QueryResponse rsp;

        try {
            rsp = buildSolrServer(getSolrUrl() + "/commodity").query(params);

        } catch (SolrServerException e) {
            throw new ServiceException("Solr server error", e);
        }
        // 返回查询结果
        SimpleOrderedMap<SolrDocumentList> mltResults = (SimpleOrderedMap<SolrDocumentList>) rsp.getResponse().get("moreLikeThis");

        return mltResults;
    }

}
